/*
 * Copyright 2003 Solers Corporation.  All rights reserved.
 *
 * Modification and use of this SLP API software and
 * associated documentation ("Software") is permitted provided that the
 * conditions specified in the license.txt file included within this
 * distribution are met.
 *
 */

package com.solers.slp;

import java.io.ByteArrayOutputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.Locale;
import java.util.StringTokenizer;
import java.util.Vector;

/**
 * The ServiceRegistration SLP Message.
 * 
 * @author Patrick Callis
 */
class ServiceRegistration extends SLPMessage {

	private ServiceURL _url;
	private Vector _attributes;
	private String _scopes;
	private AuthenticationBlock[] _attrAuths;

	ServiceRegistration(ServiceURL url, Vector attributes, Locale locale,
			String scopes) {
		super(locale, SRVREG);
		_url = url;
		_attributes = attributes;
		_scopes = scopes;
		_attrAuths = new AuthenticationBlock[0];
	}

	void sign() throws ServiceLocationException {
		_url.sign();
		SLPConfiguration conf = ServiceLocationManager.getConfiguration();
		if (conf.getSecurityEnabled() && _attributes.size() > 0) {
			try {
				StringTokenizer st = new StringTokenizer(conf.getSPI(), ",");
				_attrAuths = new AuthenticationBlock[st.countTokens()];
				int i = 0;
				while (st.hasMoreElements()) {
					String spi = st.nextToken();
					int timestamp = ServiceLocationManager.getTimestamp();
					timestamp += _url.getLifetime();
					byte[] data = getAuthData(spi, timestamp);
					_attrAuths[i++] = new AuthenticationBlock((short) 2, spi,
							timestamp, data, null);
				}
			} catch (IOException e) {
				throw new ServiceLocationException("Could not sign URL",
						ServiceLocationException.AUTHENTICATION_FAILED);
			}
		}
	}

	private byte[] getAuthData(String spi, int timestamp) throws IOException {
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		DataOutputStream dos = new DataOutputStream(bos);

		byte[] temp = spi.getBytes();
		dos.writeShort(temp.length);
		dos.write(temp);

		dos.writeShort((short) ServiceLocationAttribute
				.calcAttrListSize(_attributes));
		Iterator i = _attributes.iterator();
		while (i.hasNext()) {
			((ServiceLocationAttribute) i.next()).writeAttribute(dos);
			if (i.hasNext()) {
				dos.write(",".getBytes());
			}
		}

		dos.writeInt(timestamp);
		return bos.toByteArray();
	}

	protected void writeBody(DataOutput out) throws java.io.IOException {
		_url.writeExternal(out); // URL entry
		byte[] temp = _url.getServiceType().toString().getBytes();
		out.writeShort((short) temp.length); // length of service type
		out.write(temp); // service type

		temp = _scopes.getBytes();
		out.writeShort((short) temp.length); // length of scopes
		out.write(temp);

		// Attributes
		out.writeShort((short) ServiceLocationAttribute
				.calcAttrListSize(_attributes));
		Iterator i = _attributes.iterator();
		while (i.hasNext()) {
			((ServiceLocationAttribute) i.next()).writeAttribute(out);
			if (i.hasNext()) {
				out.write(",".getBytes());
			}
		}

		// # of attr auths
		out.write((byte) _attrAuths.length);
		for (int j = 0; j < _attrAuths.length; j++) {
			_attrAuths[j].writeBlock(out);
		}
	}

	protected int calcSize() {
		int size = _url.calcSize() // URL-Entry
				+ 2 // Length of service type
				+ _url.getServiceType().toString().length() + 2 // Length of
																// scope list
				+ _scopes.getBytes().length // scopes
				+ 2 // length of attr list
				+ ServiceLocationAttribute.calcAttrListSize(_attributes) + 1; // #
																				// of
																				// attr
																				// auths

		for (int i = 0; i < _attrAuths.length; i++) {
			size += _attrAuths[i].calcSize();
		}

		return size;
	}

	public String toString() {
		String s = "ServiceRegistration: " + "URL: " + _url + " Attributes: ";

		Iterator i = _attributes.iterator();
		while (i.hasNext()) {
			s += i.next() + " ";
		}
		return s;
	}
}
